Generic Migrations in Fluent

So we pre-populated our database with initial data in previous two tips and even added related data. That’s fine, but it is all related to #postgresql.

What if we wanted to make it work with all the databases that Vapor supports.

Well in that case we need a Generic Migration.


import Async
import Fluent
import Foundation

public final class TestModel<D>: Model where D: QuerySupporting {

  public typealias Database = D
  public typealias ID = Int
  public static var idKey: IDKey { return \.id }
  public static var entity: String {
    return "testModel"
  }
  
  public static var database: DatabaseIdentifier<D> {
    return .init("test")
  }
  
  var id: Int?
  var name: String
  var num : Int
  
  init(name: String, num: Int) {
    self.name = name
    self.num = num
  }
}

extension TestModel: Migration where D: SchemaSupporting, D: QuerySupporting { }

extension MigrationConfig {
  public mutating func addTestModels<D>(for database: DatabaseIdentifier<D>)
    where D: QuerySupporting, D: IndexSupporting {
      self.add(model: TestModel<D>.self, database: database)
  }
}

let testNames = [
  "test_Name_1",
  "test_Name_2",
  "test_Name_3"
]

internal struct TestModelMigration<D>: Migration where D: QuerySupporting & SchemaSupporting {
  typealias Database = D
  
  static func prepare(on connection: Database.Connection) -> Future<Void> {
    //Insert all names
    let futures : [EventLoopFuture<Void>] = testNames.map { name in
      return TestModel<D>(name: name, num: 1).create(on: connection).map(to: Void.self) { _ in return }
    }
    return Future<Void>.andAll(futures, eventLoop: connection.eventLoop)
  }
  
  static func revert(on connection: Database.Connection) -> Future<Void> {
    do {
      // Delete all names
      let futures = try testNames.map { name in
        return try TestModel<D>.query(on: connection).filter(\TestModel.name, .equals, .data(name)).delete()
      }
      return Future<Void>.andAll(futures, eventLoop: connection.eventLoop)
    }
    catch {
      return connection.eventLoop.newFailedFuture(error: error)
    }
  }

}

Run your migration

In configure.swift add the code:

migrations.add(model: TestModel<PostgreSQLDatabase>.self, database: .psql)
migrations.add(migration: TestModelMigration<PostgreSQLDatabase>.self, database: .psql)

And the data is added:



Prev: Pre-populating Related Tables in Vapor

Next: Generic Pre-populated Models in Fluent


Vapor 3 Tutorial Start




#tutorial #fluent #vapor #model #migration #db #generic #pub #pre-populate